#ifndef __F_FUNC_
#define __F_FUNC_

#define PRINT_MSG

 

#include <stdio.h>
#include <string.h>
#include <vector>
#include <time.h>
#ifdef WINDOWS
#include <Windows.h>
#else
#include <sys/types.h>
#include <sys/mman.h>
#endif

using namespace std;

typedef struct
{	
	unsigned int type;// RAID
	unsigned int num_disk;// 
	unsigned int num_blocks;// 
	unsigned int size_block;// 
	
}header;

header data;

vector<char*>files;//       .
		//UnmapViewOfFile(addr)
#ifdef WINDOWS
vector<HFILE>fd_files;
		//CloseHandle((HANDLE)fd);
vector<HANDLE>mapped_files; 
		//CloseHandle(cddbmap); 
#else
vector<FILE*>fd_files;
#endif
const char* raid_config = "./raid.config";


bool (*read_raid_func)(FILE*,int);
bool (*write_raid_func)(FILE*,int,int) ;
bool (*rebuild_raid_func)() ;


//=====================================
//          WRITE
//=====================================
bool write_raid_0(FILE* src,int dst,int size)
{
    int read_block = data.size_block/data.num_disk; if(data.size_block%data.num_disk!=0) read_block++;
	int shift = (dst-1)*read_block;
	int i=0;
	int cur_shift = 0;
	for(i=0;i<data.num_disk;i++)
	{
		cur_shift = fread((files.at(i))+shift,1,read_block,src);
		if(cur_shift!=read_block) 
		{
			memset(files.at(i)+shift+cur_shift,0,read_block-cur_shift);
		}	
	}
	return true;
}
bool write_raid_1(FILE* src,int dst,int size)
{
	int shift = dst*data.size_block;
	int read_block = data.size_block;
	int i=0;
	int cur_shift = 0;
	for(i=0;i<data.num_disk;i++)
	{
		cur_shift = fread((files.at(i))+shift,1,read_block,src);
		if(cur_shift!=read_block) 
		{
			memset(files.at(i)+shift+cur_shift,0,read_block-cur_shift);
		}	
		fseek(src,0,SEEK_SET);
	}
	return true;
}
bool write_raid_01(FILE* src,int dst,int size)
{	
	int read_block = data.size_block/2; if(data.size_block%2!=0)read_block++;
	int shift = (dst-1)*read_block;
	int i=0;
	int cur_shift = 0;
	for(i=0;i<2;i++)
	{
		cur_shift = fread((files.at(i))+shift,1,read_block,src);
		if(cur_shift!=read_block) 
		{
			memset(files.at(i)+shift+cur_shift,0,read_block-cur_shift);
		}	
	}
	
	for(i=2;i<data.num_disk;i++)
	{
		memcpy(files.at(i)+shift,(files.at(i%2))+shift,read_block);
	}
	return true;
	
}
bool write_raid_10(FILE* src,int dst,int size)
{

	int read_block = data.size_block/2;if(data.size_block%2!=0)read_block++;
	int shift = (dst-1)*read_block;
	int i=0,j=0;
	int cur_shift = 0;

	for(j=0;j<data.num_disk;j+=2)
	{
		for(i=0;i<2;i++)
		{
			cur_shift = fread((files.at(j+i))+shift,1,read_block,src);
			if(cur_shift!=read_block) 
			{
				memset(files.at(j+i)+shift+cur_shift,0,read_block-cur_shift);
			}	
		}
		fseek(src,0,SEEK_SET);
	}
	
	return true;
}
bool write_raid_3(FILE* src,int dst,int size)
{
	int read_block = data.size_block/(data.num_disk-1);if(data.size_block%(data.num_disk-1)!=0) read_block++;
	int shift = (dst-1)*read_block;
	int i=0,j=0;
	int cur_shift = 0;
	char check_sum = 0;
	for(j=0;j<read_block;j++)
	{
	 check_sum = 0;
		for(i=0;i<data.num_disk-1;i++)
		{
			if(fread((files.at(i))+shift+j,1,1,src)!=1) 
			{
				*((files.at(i))+shift+j)=0;
			}	
			check_sum = check_sum xor *((files.at(i))+shift+j);
		}
		*((files.at(data.num_disk-1))+shift+j) = check_sum;
	}
	return true;
}
bool write_raid_4(FILE* src,int dst,int size)
{
	int read_block = data.size_block/(data.num_disk-1);if(data.size_block%(data.num_disk-1)!=0) read_block++;
	int shift = (dst-1)*read_block;
	int i=0,j=0;
	int cur_shift = 0;
	for(j=0;j<read_block;j++)
		*((files.at(data.num_disk-1))+shift+j) = 0;	
		
	for(i=0;i<data.num_disk-1;i++)
	{
		cur_shift = fread((files.at(i))+shift,1,read_block,src);
		if(cur_shift!=read_block) 
		{
			memset(files.at(i)+shift+cur_shift,0,read_block-cur_shift);
		}	
		for(int j=0;j<read_block;j++)
			*((files.at(data.num_disk-1))+shift+j) = *((files.at(data.num_disk-1))+shift+j) xor *((files.at(i))+shift+j);	
	}
	return true;
}
bool write_raid_5(FILE* src,int dst,int size)
{
	
	int read_block = data.size_block/(data.num_disk-1);if(data.size_block%(data.num_disk-1)!=0) read_block++;
	int shift = (dst-1)*read_block;
	int i=0,j=0;
	int cur_shift = 0;
	int cs_disk = dst % data.num_disk;
	for(j=0;j<read_block;j++)
		*((files.at(cs_disk))+shift+j) = 0;	
	
	
	for(i=0;i<data.num_disk;i++)
	{
		if(i!=cs_disk)
		{
			cur_shift = fread((files.at(i))+shift,1,read_block,src);
			if(cur_shift!=read_block) 
			{
				memset(files.at(i)+shift+cur_shift,0,read_block-cur_shift);
			}	
			for(int j=0;j<read_block;j++)
				*((files.at(cs_disk))+shift+j) = *((files.at(cs_disk))+shift+j) xor *((files.at(i))+shift+j);	
		}
	}
	return true;
	
}
//=====================================
//          READ
//=====================================
bool read_raid_0(FILE* dst,int src)
{
	int read_block = data.size_block/data.num_disk; if(data.size_block%data.num_disk!=0) read_block++;	
	int shift = (src-1)*read_block;
	int i=0;
int write_size = 0;
	for(i=0;i<data.num_disk;i++)
	{
		if(write_size+read_block<=data.size_block)
		write_size+= fwrite((files.at(i))+shift,1,read_block,dst);
		else
		write_size+= fwrite((files.at(i))+shift,1,data.size_block-write_size,dst);
	}
	return true;
}
bool read_raid_1(FILE* dst,int src)
{
	int shift = src*data.size_block;
	int read_block = data.size_block;
	int i=0;
	int cur_shift = 0;

	for(i=1;i<data.num_disk;i++)
	{
		if(memcmp((files.at(0))+shift,(files.at(i))+shift,read_block)!=0)
		{
			cout<<"data on the drives are different. "<<endl;
			return false;
		}
	}
	
	fwrite((files.at(0))+shift,1,read_block,dst);

	return true;
}
bool read_raid_01(FILE* dst,int src)
{

	int read_block = data.size_block/2;if(data.size_block%2!=0)read_block++;
	int shift = (src-1)*read_block;
	int i=0;
	int cur_shift = 0;
        int write_size = 0;
	for(i=0;i<2;i++)
	{
	     if(write_size+read_block<=data.size_block)
		write_size+= fwrite((files.at(i))+shift,1,read_block,dst);
	     else
		write_size+= fwrite((files.at(i))+shift,1,data.size_block-write_size,dst);
	}
	return true;
}
bool read_raid_10(FILE* dst,int src)
{
	int read_block = data.size_block/2;if(data.size_block%2!=0)read_block++;
	int shift = (src-1)*read_block;
	int i=0;
	int cur_shift = 0;
        int write_size = 0;
	for(i=0;i<2;i++)
	{
	     if(write_size+read_block<=data.size_block)
		write_size+= fwrite((files.at(i))+shift,1,read_block,dst);
	     else
		write_size+= fwrite((files.at(i))+shift,1,data.size_block-write_size,dst);
	}
	return true;
}
bool read_raid_3(FILE* dst,int src)
{
	int read_block = data.size_block/(data.num_disk-1);if(data.size_block%(data.num_disk-1)!=0) read_block++;
	int shift = (src-1)*read_block;
	int i=0,j=0;
	int cur_shift = 0;
	char check_sum = 0;
	int write_size = 0;
	for(j=0;j<read_block;j++)
	{
		check_sum = 0;
		for(i=0;i<data.num_disk-1;i++)
		{
			check_sum = check_sum xor *((files.at(i))+shift+j);
		}
		if(*((files.at(data.num_disk-1))+shift+j) != check_sum)
		{
			cout<<"check sum error"<<endl;
			return false;
		}
		for(i=0;i<data.num_disk-1 && write_size<data.size_block;i++,write_size++)
			fwrite((files.at(i))+shift+j,1,1,dst);	
	}
	return true;
	
}
bool read_raid_4(FILE* dst,int src)
{
	int read_block = data.size_block/(data.num_disk-1);if(data.size_block%(data.num_disk-1)!=0) read_block++;
	int shift = (src-1)*read_block;
	int i=0,j=0;
	int cur_shift = 0;
	char check_sum;
	int write_size = 0;
	for(j=0;j<read_block;j++)
	{
		check_sum = 0;
		for(i=0;i<data.num_disk-1;i++)
		{
			check_sum = check_sum xor *((files.at(i))+shift+j);
		}
		if(*((files.at(data.num_disk-1))+shift+j) != check_sum)
		{
			cout<<"check sum error"<<endl;
			return false;
		}
	}
	for(i=0;i<data.num_disk-1;i++)
	{
		if(write_size+read_block<=data.size_block)
			write_size+= fwrite((files.at(i))+shift,1,read_block,dst);
		else
			write_size+= fwrite((files.at(i))+shift,1,data.size_block-write_size,dst);
	}
	return true;
}
bool read_raid_5(FILE* dst,int src)
{
	int cs_disk = src%data.num_disk;
	int read_block = data.size_block/(data.num_disk-1);if(data.size_block%(data.num_disk-1)!=0) read_block++;
	int shift = (src-1)*read_block;
	int i=0,j=0;
	int cur_shift = 0;
	char check_sum;
	int write_size = 0;

	for(j=0;j<read_block;j++)
	{
		check_sum = 0;
		for(i=0;i<data.num_disk;i++)
		{
			if(i!=cs_disk)
				check_sum = check_sum xor *((files.at(i))+shift+j);
		}
		
		if(*((files.at(cs_disk))+shift+j) != check_sum)
		{
			cout<<"check sum error"<<endl;
			return false;
		}
	}
	for(i=0;i<data.num_disk;i++)
        {
		if(i!=cs_disk)
			if(write_size+read_block<=data.size_block)
				write_size+= fwrite((files.at(i))+shift,1,read_block,dst);
			else
				write_size+= fwrite((files.at(i))+shift,1,data.size_block-write_size,dst);
	}
	return true;
}



//=====================================
//          REBUILD
//=====================================
bool rebuild_raid_0()
{
	cout<<"RAID 0 can't rebuild disks"<<endl; 
	return false;
}
bool rebuild_raid_1()
{
	int i=0,need_rebuid = 0;
	int etalon = 0;
	int read_block = data.size_block;
	int file_size = data.num_blocks *data.size_block ;
	char filename[15];
	FILE* fd;
	for(i=0;i<data.num_disk;i++)
		if(files.at(i)==NULL)
			need_rebuid++;
	if(need_rebuid == data.num_disk)
	{
		cout<<"Can't rebuild RAID 1 disks. There isn't any disks with data "<<endl; 
		return false;
	}
	for(i=0;i<data.num_disk;i++)
		if(files.at(i)!=NULL)
		{
			etalon =i; break;
		}

	for(i=0;i<data.num_disk;i++)
	{
		if(i!=etalon&&files.at(i)!=NULL)
		if(memcmp((files.at(etalon)),(files.at(i)),file_size)!=0)
		{
			cout<<"data on the disks are different. "<<endl;
			return false;
		}
	}
	for(i=0;i<data.num_disk;i++)
	{
		if(files.at(i)==NULL)
		{
		sprintf(filename,"./disk%d",i);
		fd = fopen(filename,"wb+");
		if(fd==NULL)
		{
			cout<<"can't create/open file "<<filename<<endl;
			return false;
		}
		
		fwrite((files.at(etalon)),sizeof(char),file_size,fd);
		fclose(fd);
		}
	}	
	return true;
}
bool rebuild_raid_01()
{
	
	int i=0,need_rebuid = 0,j=0;
	int etalon = 0;
	int read_block = data.size_block;
	int file_size = data.num_blocks *data.size_block/2 ; if(data.size_block%2!=0)file_size+=data.num_blocks;
	char filename[15];
	FILE* fd;
	for(j=0;j<2;j++)
	{
		need_rebuid = 0;
		for(i=j;i<data.num_disk;i+=2)
			if(files.at(i)==NULL)
				need_rebuid++;
				
		if(need_rebuid == data.num_disk/2)
		{
			cout<<"Can't rebuild RAID 01 disks. There isn't any disks with data from RAID1 part "<<endl; 
			return false;
		}
	}
	for(j=0;j<2;j++)
	{
		for(i=j;i<data.num_disk;i+=2)
			if(files.at(i)!=NULL)
			{
				etalon =i; break;
			}

		for(i=j;i<data.num_disk;i+=2)
		{
			if(i!=etalon&&files.at(i)!=NULL)
				if(memcmp((files.at(etalon)),(files.at(i)),file_size)!=0)
				{
					cout<<"data on the disks are different. "<<endl;
					return false;
				}
		}
	}
	
	for(j=0;j<2;j++)
	{
		for(i=j;i<data.num_disk;i+=2)
			if(files.at(i)!=NULL)
			{
				etalon =i; break;
			}
		for(i=j;i<data.num_disk;i+=2)
		{
			if(files.at(i)==NULL)
			{
				sprintf(filename,"./disk%d",i);
				fd = fopen(filename,"wb+");
				if(fd==NULL)
				{
					cout<<"can't create/open file "<<filename<<endl;
					return false;
				}
			fwrite((files.at(etalon)),sizeof(char),file_size,fd);
			fclose(fd);
			}
		}	
	}
	
	return true;
}
bool rebuild_raid_10()
{

int i=0,need_rebuid = 0,j=0;
	int etalon[2] = {0,0};
	int read_block = data.size_block;
	int file_size = data.num_blocks *data.size_block/2 ; if(data.size_block%2!=0)file_size+=data.num_blocks;
	char filename[15];
	FILE* fd;
	for(j=0;j<2;j++)
	{
		need_rebuid = 0;
		for(i=j;i<data.num_disk;i+=2)
			if(files.at(i)==NULL)
				need_rebuid++;
				
		if(need_rebuid == data.num_disk/2)
		{
			cout<<"Can't rebuild RAID 10 disks. There isn't any disks with data from RAID1 part "<<endl; 
			return false;
		}
	}
	for(j=0;j<2;j++)
	{
		for(i=0;i<data.num_disk;i+=2)
		{
			if(files.at(i+j)!=NULL)
			{
				etalon[j] =i+j; i=data.num_disk;
			}
		}
	}	
	
	for(i=0;i<data.num_disk;i+=2)
	{
		for(j=0;j<2;j++)
		{
			if(i+j!=etalon[j]&&files.at(i+j)!=NULL)
			{
				if(memcmp((files.at(etalon[j])),(files.at(i+j)),file_size)!=0)
				{
					cout<<"data on the disks are different. "<<endl;
					return false;
				}
			}
		}
	}
	for(i=0;i<data.num_disk;i+=2)
	{	
		for(j=0;j<2;j++)
		{
			if(files.at(i+j)==NULL)
			{
				sprintf(filename,"./disk%d",i+j);
				fd = fopen(filename,"wb+");
				if(fd==NULL)
				{
					cout<<"can't create/open file "<<filename<<endl;
					return false;
				}
				fwrite((files.at(etalon[j])),sizeof(char),file_size,fd);
				fclose(fd);
			}
		}	
	}

	return true;
}
bool rebuild_raid_3()
{
	int i=0,need_rebuid = 0,j=0;
	int etalon = 0;
    int read_block = data.size_block/(data.num_disk-1);if(data.size_block%(data.num_disk-1)!=0) read_block++;
	int file_size = data.num_blocks * read_block;
	char filename[15];
	char checksum =0;
	FILE* fd;
	for(i=0;i<data.num_disk;i++)
		if(files.at(i)==NULL)
			need_rebuid++;
			
	if(need_rebuid > 1)
	{
		cout<<"RAID 3  can rebuild only 1 disk"<<endl; 
		return false;
	}
	if(need_rebuid<1)
		return true;
		
	for(i=0;i<data.num_disk;i++)
		if(files.at(i)==NULL)
		{
			etalon =i; break;
		}
		
	sprintf(filename,"./disk%d",etalon);
	fd = fopen(filename,"wb+");
	if(fd==NULL)
	{
			cout<<"can't create/open file "<<filename<<endl;
			return false;
	}
	for(j=0;j<file_size;j++)
	{	
		checksum = 0;
		for(i=0;i<data.num_disk;i++)
		{
			if(files.at(i)!=NULL)
			{
				checksum = checksum xor *((files.at(i))+j);
			}
		}
		fwrite(&checksum,sizeof(char),1,fd);		
	}
	fclose(fd);
	return true;
}
bool rebuild_raid_4()
{
int i=0,need_rebuid = 0,j=0;
	int etalon = 0;
	int read_block = data.size_block/(data.num_disk-1);if(data.size_block%(data.num_disk-1)!=0) read_block++;
	int file_size = data.num_blocks * read_block;
	char filename[15];
	char checksum =0;
	FILE* fd;
	for(i=0;i<data.num_disk;i++)
		if(files.at(i)==NULL)
			need_rebuid++;
			
	if(need_rebuid > 1)
	{
		cout<<"RAID 3  can rebuild only 1 disk"<<endl; 
		return false;
	}
	if(need_rebuid<1)
		return true;
		
	for(i=0;i<data.num_disk;i++)
		if(files.at(i)==NULL)
		{
			etalon =i; break;
		}
		
	sprintf(filename,"./disk%d",etalon);
	fd = fopen(filename,"wb+");
	if(fd==NULL)
	{
		cout<<"can't create/open file "<<filename<<endl;
		return false;
	}
	for(j=0;j<file_size;j++)
	{	
		checksum = 0;
		for(i=0;i<data.num_disk;i++)
		{
			if(files.at(i)!=NULL)
			{
				checksum = checksum xor *((files.at(i))+j);
			}
		}
		fwrite(&checksum,sizeof(char),1,fd);		
	}
	fclose(fd);
	return true;
}
bool rebuild_raid_5()
{
	
	int i=0,need_rebuid = 0,j=0;
	int etalon = 0;
	int read_block = data.size_block/(data.num_disk-1); if(data.size_block%(data.num_disk-1)!=0) read_block++;
	int file_size = data.num_blocks * read_block;
	char filename[15];
	char checksum =0;
	FILE* fd;
	for(i=0;i<data.num_disk;i++)
		if(files.at(i)==NULL)
			need_rebuid++;

	if(need_rebuid > 1)
	{
		cout<<"RAID 3  can rebuild only 1 disk"<<endl; 
		return false;
	}
	if(need_rebuid<1)
		return true;
		
	for(i=0;i<data.num_disk;i++)
		if(files.at(i)==NULL)
		{
			etalon =i; break;
		}
		
	sprintf(filename,"./disk%d",etalon);
	fd = fopen(filename,"wb+");
	if(fd==NULL)
	{
			cout<<"can't create/open file "<<filename<<endl;
			return false;
	}
	
	for(j=0;j<file_size;j++)
	{	
		checksum = 0;
		for(i=0;i<data.num_disk;i++)
		{
			if(files.at(i)!=NULL)
			{
				checksum = checksum xor *((files.at(i))+j);
			}
		}
		fwrite(&checksum,sizeof(char),1,fd);	
				
	}
	fclose(fd);
	return true;
}

//=====================================
//          BUILD
//=====================================
bool build_raid(int type, int num,int blocks,int size)
{
	data.type = type;
	data.num_disk = num;
	data.num_blocks = blocks;
	data.size_block = size;
	
	int file_size;  
	int block_size = 0;
	int i;
	FILE* fd;
	if(type==1)
	{	
		if(num<2)
		{
			cout<<"you need at least 2 disks for RAID 1"<<endl;
			return false;
		}
		file_size = blocks*size;
	}
	else if(type == 0)
	{	
		if(num<2)
		{
			cout<<"you need at least 2 disks for RAID 1"<<endl;
			return false;
		}
		block_size = size/(num);if(size%(num)!=0) block_size++;
		file_size = blocks*block_size;
	}
	else if(type==11 || type == 10)
	{
		if(num<4)
		{
			cout<<"you need at least 4 disks for RAID 1+0 (0+1)"<<endl;
			return false;
		}
		if(num%2!=0)
		{
			cout<<"you need even number of disks for RAID 1+0 (0+1)"<<endl;
			return false;
		}
		block_size = size/2;if(size%2!=0) block_size++;
		file_size = blocks*block_size;
	}
	else
	{
		if(num<3)
		{
			cout<<"you need at least 3 disks for RAID 3(4,5)"<<endl;
			return false;
		}
		block_size = size/(num-1);if(size%(num-1)!=0) block_size++;
		file_size = blocks*block_size;
	}

	char* disk_data = new char[file_size];
	memset(disk_data,0,file_size);
	char filename[15];
	fd = fopen(raid_config,"wb+");
	if(fd==NULL)
	{
			cout<<"can't create/open raid config file "<<raid_config<<endl;
			return false;
	}
	fwrite(&data,sizeof(header),1,fd);	
	fclose(fd);
	for(i=0;i<num;i++)
	{
	
		sprintf(filename,"./disk%d",i);
		fd = fopen(filename,"wb+");
		if(fd==NULL)
		{
			cout<<"can't create/open file "<<filename<<endl;
			return false;
		}
		
		fwrite(disk_data,sizeof(char),file_size,fd);
		fclose(fd);
	}
	
	return true;
}
//=====================================
//        CHECK
//=====================================
bool check_disks()
{
	
	header other_data;
	int file_size;  
	int block_size=0;
	int i;
	char name[10];
	FILE* fd;
	
#ifdef WINDOWS
	HFILE fd_1;
	OFSTRUCT ttt;
	HANDLE cddbmap;
	void *cddb;
#else
	void* cddb;
#endif
	
	fd = fopen(raid_config,"rb");
	if(fd==NULL)
	{
		cout<<"can't open raid config file  "<<endl;
		return false;
	}
	fread(&data,sizeof(header),1,fd);
	fclose(fd);
	
	if(data.type==1)
	{	
		file_size = data.num_blocks*data.size_block;
	}
	else if(data.type == 0)
	{
		block_size = data.size_block/data.num_disk;
			if(data.size_block%data.num_disk!=0) block_size++;
		file_size = data.num_blocks*block_size;
	}
	else if( data.type == 11 ||data.type == 10)
	{
		block_size = data.size_block/2;
			if(data.size_block%2!=0) block_size++;
		file_size = data.num_blocks*block_size;
	}
	else
	{
		block_size = data.size_block/(data.num_disk-1);
			if(data.size_block%(data.num_disk-1)!=0) block_size++;
		file_size = data.num_blocks*block_size;

	}
	for(i=0;i<data.num_disk;i++)
	{
		sprintf(name,"./disk%d",i);
		
#ifdef WINDOWS
	
		fd_1 = OpenFile(name,&ttt,OF_READWRITE);
		fd_files.push_back(fd_1);

		if(fd_1==HFILE_ERROR)
		{
			cout<<"can't create/open file "<<name<<endl;
			return false;
		}

		cddbmap = CreateFileMapping((HANDLE)fd_1, NULL, PAGE_READWRITE, 0, 0, NULL);
		mapped_files.push_back(cddbmap);
		
		cddb = MapViewOfFile(cddbmap, FILE_MAP_WRITE, 0, 0, 0);
		if(cddb==NULL)
		{
			cout<<"error mapping file"<<endl;
			return false;
		}
		files.push_back((char*)cddb);
#else
		
		fd = fopen(name,"rb+");
		if(fd==NULL)
		{
			cout<<"can't create/open file "<<name<<endl;
			return false;
		}
		
		cddb = mmap(0,file_size,PROT_WRITE|PROT_READ,MAP_SHARED,fileno(fd),0);
		files.push_back((char*)cddb);
		fd_files.push_back(fd);
#endif
		
	}
	
	switch(data.type)
	{
		case 0:
			 read_raid_func = &read_raid_0;
			 write_raid_func = &write_raid_0;
		break;
		case 1:
			 read_raid_func = &read_raid_1;
			 write_raid_func = &write_raid_1;
		break;
		case 3:
			 read_raid_func = &read_raid_3;
			 write_raid_func = &write_raid_3;
		break;
		case 4:
			 read_raid_func = &read_raid_4;
			 write_raid_func = &write_raid_4;
			 rebuild_raid_func = &rebuild_raid_4;
		break;
		case 5:
			 read_raid_func = &read_raid_5;
			 write_raid_func = &write_raid_5;
		break;
		case 10:
			 read_raid_func = &read_raid_10;
			 write_raid_func = &write_raid_10;
		break;
		case 11:
			 read_raid_func = &read_raid_01;
			 write_raid_func = &write_raid_01;
		break;
	}
	return true;
}


//=====================================
//        CHECK
//=====================================
void load_disks()
{
	
	header other_data;
	int file_size;  
	int i;
	char name[10];
	FILE* fd;
	int block_size;
	
#ifdef WINDOWS
	HFILE fd_1;
	OFSTRUCT ttt;
	HANDLE cddbmap;
	void *cddb;
#else
	void* cddb;
#endif
	fd = fopen(raid_config,"rb");
	if(fd==NULL)
	{
		cout<<"can't open raid config file  "<<endl;
		return ;
	}
	fread(&data,sizeof(header),1,fd);
	fclose(fd);
	
	if(data.type==1)
	{	
		file_size = data.num_blocks*data.size_block;
	}
	else if(data.type == 0)
	{
		block_size = data.size_block/data.num_disk;
			if(data.size_block%data.num_disk!=0) block_size++;
		file_size = data.num_blocks*block_size;
	}
	else if( data.type == 11 ||data.type == 10)
	{
		block_size = data.size_block/2;
			if(data.size_block%2!=0) block_size++;
		file_size = data.num_blocks*block_size;
	}
	else
	{
		block_size = data.size_block/(data.num_disk-1);
			if(data.size_block%(data.num_disk-1)!=0) block_size++;
		file_size = data.num_blocks*block_size;

	}
	
	for(i=0;i<data.num_disk;i++)
	{
		sprintf(name,"./disk%d",i);
			
#ifdef WINDOWS
	
		fd_1 = OpenFile(name,&ttt,OF_READWRITE);

		if(fd_1==HFILE_ERROR)
		{
			cout<<"can't find file "<<name<<endl;
			files.push_back(NULL);
			fd_files.push_back(fd_1);
			mapped_files.push_back(cddbmap);
		}
		else
		{	
			fd_files.push_back(fd_1);
			cddbmap = CreateFileMapping((HANDLE)fd_1, NULL, PAGE_READWRITE, 0, 0, NULL);
			mapped_files.push_back(cddbmap);
			
			cddb = MapViewOfFile(cddbmap, FILE_MAP_WRITE, 0, 0, 0);
			if(cddb==NULL)
			{
				cout<<"error mapping file"<<endl;
				return;
			}
			files.push_back((char*)cddb);
		}
#else
		
		fd = fopen(name,"rb+");
		if(fd==NULL)
		{
			cout<<"can't find "<<name<<endl;
			files.push_back(NULL);
		}
		else
		{
			cddb = mmap(0,file_size,PROT_WRITE|PROT_READ,MAP_SHARED,fileno(fd),0);
			files.push_back((char*)cddb);
		}
		
		fd_files.push_back(fd);
#endif
		
	}
	
	switch(data.type)
	{
		case 0:
			  rebuild_raid_func = &rebuild_raid_0;
		break;
		case 1:
			 rebuild_raid_func = &rebuild_raid_1;
		break;
		case 3:
			 rebuild_raid_func = &rebuild_raid_3;
		break;
		case 4:
			 rebuild_raid_func = &rebuild_raid_4;
		break;
		case 5:
			 rebuild_raid_func = &rebuild_raid_5;
		break;
		case 10:
			 rebuild_raid_func = &rebuild_raid_10;
		break;
		case 11:
			 rebuild_raid_func = &rebuild_raid_01;
		break;
	}
	return;
}


//=====================================
//          CLOSE
//=====================================
void close_raid_files()
{
	int i;
	for(i=0;i<data.num_disk;i++)
	{

#ifdef WINDOWS
	UnmapViewOfFile((void*)(files.at(i)));
	
	CloseHandle(mapped_files.at(i)); 
	
	CloseHandle((HANDLE)fd_files.at(i));
#else
	fclose(fd_files.at(i));
#endif
	}
}

void unload_raid_files()
{
	int i;
	for(i=0;i<data.num_disk;i++)
	{

		if(files.at(i)!=NULL){
		#ifdef WINDOWS
			UnmapViewOfFile((void*)(files.at(i)));
			
			CloseHandle(mapped_files.at(i)); 
			
			CloseHandle((HANDLE)fd_files.at(i));
		#else
			fclose(fd_files.at(i));
		#endif
		}
	}
}

#endif
